from insts.inst import NoOperandInstruction


class X2Y(NoOperandInstruction):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        self.y = 'int'

    def execute(self, frame):
        stack = frame.getOperandStack()
        var1 = None
        if self.x == 'int':
            var1 = stack.popInt()
        elif self.x == 'float':
            var1 = stack.popFloat()
        elif self.x == 'long':
            var1 = stack.popLong()
        elif self.x == 'double':
            var1 = stack.popDouble()
        else:
            raise ValueError("Invalid type for x")
        if self.y == 'int':
            stack.pushInt(var1)
        elif self.y == 'float':
            stack.pushFloat(var1)
        elif self.y == 'long':
            stack.pushLong(var1)
        elif self.y == 'double':
            stack.pushDouble(var1)
        else:
            raise ValueError("Invalid type for y")


class I2L(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        self.y = 'long'


class I2F(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        self.y = 'float'


class I2D(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        self.y = 'double'


class L2I(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'long'
        self.y = 'int'


class L2F(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'long'
        self.y = 'float'


class L2D(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'long'
        self.y = 'double'


class F2I(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'float'
        self.y = 'int'


class F2L(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'float'
        self.y = 'long'


class F2D(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'float'
        self.y = 'double'


class D2I(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'double'
        self.y = 'int'


class D2L(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'double'
        self.y = 'long'


class D2F(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'double'
        self.y = 'float'


class I2B(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        # self.y = 'byte'
        self.y = 'int'


class I2C(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        # self.y = 'char'
        self.y = 'int'


class I2S(X2Y):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.x = 'int'
        # self.y ='short'
        self.y = 'int'
        